﻿//!CompilerOption:Optimize:On
// TSMBuddy Botbase by XCoord

#region Usings

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using CommonBehaviors.Actions;

using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using Styx.CommonBot.Profiles;
using Styx.Plugins;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Action = Styx.TreeSharp.Action;
using Styx.WoWInternals.WoWObjects;

#endregion

namespace TSMBuddy
{
    public class TSMBuddy : BotBase
    {
        #region Static Members

        public static WoWPoint _gotoLocation;
        public static bool _init = false;
        private static Composite _root;

        public static Helpers.States State;
        public static volatile bool scanComplete = false;
        private static int _waitSeconds = 10;

        private static LocalPlayer Me { get { return StyxWoW.Me; } }

        #endregion

        #region Fields

        #endregion

        #region Constructor

        public static TSMBuddy Instance { get; set; }
        public TSMBuddy()
        {
            Instance = this;
        }
        #endregion

        #region Events

        #endregion

        #region Properties

        private Version Version
        {
            get { return new Version(0,1); }
        }

        #endregion

        #region Overrides

        public override string Name
        {
            get { return "TSMBuddy"; }
        }

        public override Composite Root
        {
            get
            {
                return _root ?? (_root = CreateCustomBehavior());
            }
        }

        public override PulseFlags PulseFlags
        {
            get { return PulseFlags.All; }
        }

        public override void Start()
        {
            Logging.Write("TSMBuddy started!");
            dynWaitTime();
            ChangeState(Helpers.States.CancelScan);
        }

        public override void Stop()
        {
            Logging.Write("TSMBuddy stopped!");
        }

        public override void Pulse()
        {
            //Logging.Write("Pulse");
        }

        public override void Initialize()
        {
            Logging.Write("Initialized...!");
        }

        #endregion

        #region Custom Behaviors

        private static Composite CreateCustomBehavior()
        {
            return new PrioritySelector(
                new Decorator(ret => State == Helpers.States.CancelScan, GetCancelScanBehavior()),
                new Decorator(ret => State == Helpers.States.GetMail, GetMailBehavior()),
                new Decorator(ret => State == Helpers.States.PostScan, GetPostScanBehavior()),
                new Decorator(ret => State == Helpers.States.waitCancelScanComplete, GetWaitCancelScanCompleteBehavior()),
                new Decorator(ret => State == Helpers.States.waitPostScanComplete, GetWaitPostScanCompleteBehavior()),
                new Decorator(ret => State == Helpers.States.Wait, GetWaitBehavior())
                );
        }

        private static Composite GetCancelScanBehavior()
        {
            return new Sequence(
                Helpers.GotoPoint(ret => Helpers.NearestAuctioneer.Location, ret => Helpers.NearestAuctioneer.InteractRange),
                new DecoratorContinue(ret => !AuctionFrame.Instance.IsVisible, Helpers.InteractWithUnit(ret => Helpers.NearestAuctioneer)),
                new Action(delegate
                {
                    cancelScan();
                }),
                new ActionIdle()
            );
        }

        private static Composite GetMailBehavior()
        {
            return new Sequence(
                Helpers.GotoPoint(ret => Helpers.NearestMailbox.Location, ret => Helpers.NearestMailbox.InteractRange),
                new DecoratorContinue(ret => !MailFrame.Instance.IsVisible, Helpers.InteractWithObject(ret => Helpers.NearestMailbox)),
                new DecoratorContinue(ret => (MailFrame.Instance.HasNewMail || Helpers.TakableMailCount > 0) && StyxWoW.Me.FreeNormalBagSlots > 0,
                    new Sequence(
                        new Action(delegate { MailFrame.Instance.OpenAllMail(); }),
                        new DecoratorContinue(ret => MailFrame.Instance.HasNewMail,
                            new Sequence(
                                new Wait(5, ret => false, new ActionAlwaysSucceed()),
                                new Action(delegate { Lua.DoString("CheckInbox()"); })
                                )
                            )
                        )
                    ),
                new Action(delegate
                {
                    Helpers.Wait(() => 10);
                    MailFrame.Instance.Close();
                    Logging.Write("Done checking mails!");
                    ChangeState(Helpers.States.PostScan);
                })
                );
        }

        private static Composite GetPostScanBehavior()
        {
            return new Sequence(
                Helpers.GotoPoint(ret => Helpers.NearestAuctioneer.Location, ret => Helpers.NearestAuctioneer.InteractRange),
                new DecoratorContinue(ret => !AuctionFrame.Instance.IsVisible, Helpers.InteractWithUnit(ret => Helpers.NearestAuctioneer)),
                new Action(delegate
                {
                    postScan();
                }),
                new ActionIdle()
            );
        }

        private static Composite GetWaitBehavior()
        {
            return new Sequence(
                new Action(delegate { Logging.Write("Idleing for {0} seconds.", _waitSeconds.ToString()); }),
                Helpers.Wait(() => _waitSeconds),
                new Action(delegate { Styx.Helpers.KeyboardManager.AntiAfk(); }),
                new Action(delegate { Reset(); })
            );
        }

        private static Composite GetWaitCancelScanCompleteBehavior()
        {
            return new Sequence(
                new DecoratorContinue(ret => !Helpers.checkScanComplete() || !scanComplete,
                    new Action(delegate
                    {
                        if (Lua.GetReturnVal<string>("return TSMAuctioningCancelButton:IsEnabled()", 0) == "1" || Lua.GetReturnVal<string>("return TSMAuctioningPostButton:IsEnabled()", 0) == "1")
                        {
                            Logging.Write("Cancelling...!");
                            Styx.Helpers.KeyboardManager.KeyUpDown((char)Keys.D5);
                        }
                        Logging.Write("Scanning...");
                        Thread.Sleep(500);
                    })),

                new DecoratorContinue(ret => scanComplete,
                    new Action(delegate
                    {
                        Logging.Write("All undercut auctions cancelled!");
                        scanComplete = false;
                        ChangeState(Helpers.States.GetMail);
                    }))
            );
        }

        private static Composite GetWaitPostScanCompleteBehavior()
        {
            return new Sequence(
                new DecoratorContinue(ret => !Helpers.checkScanComplete() || !scanComplete,
                    new Action(delegate
                    {
                        if (Lua.GetReturnVal<string>("return TSMAuctioningPostButton:IsEnabled()", 0) == "1")
                        {
                            Logging.Write("Posting...!");
                            Styx.Helpers.KeyboardManager.KeyUpDown((char)Keys.D5);
                        }
                        Logging.Write("Scanning...");
                        Thread.Sleep(500);
                    })),

                new DecoratorContinue(ret => scanComplete,
                    new Action(delegate
                    {
                        Logging.Write("All auctions got posted!");
                        scanComplete = false;
                        ChangeState(Helpers.States.Wait);
                    }))
            );    
        }

        #endregion

        #region Methods

        private static void cancelScan()
        { 
            string aucTab = Helpers.AHTabByName("Auctioning");

            if (aucTab == null)
            {
                Logging.Write("Could not get Auctioning Tab - Something went wrong...");  
            }

            Lua.DoString("RunMacroText(\"/click " + aucTab + "\")");
            Lua.DoString("RunMacroText(\"/click TSMStartCancelScanButton\")");

            ChangeState(Helpers.States.waitCancelScanComplete);
        }

        private static void postScan()
        {
            string aucTab = Helpers.AHTabByName("Auctioning");

            if (aucTab == null)
            {
                Logging.Write("Could not get Auctioning Tab - Something went wrong...");
            }

            Lua.DoString("RunMacroText(\"/click " + aucTab + "\")");
            Lua.DoString("RunMacroText(\"/click TSMStartPostScanButton\")");

            ChangeState(Helpers.States.waitPostScanComplete);
        }

        public static void Reset()
        {
            Logging.Write("Resetting....!");
            dynWaitTime();
            State = Helpers.States.CancelScan;
        }

        private static void dynWaitTime()
        {
            Random rnd = new Random();
            _waitSeconds = rnd.Next(1, 30);
        }

        private static void ChangeState(Helpers.States state)
        {
            State = state;
            Logging.Write("Switching state to {0}", state);
            Styx.Pathing.Navigator.Clear();
            TreeRoot.StatusText = string.Format("Current state: {0}", state);
        }

        #endregion
    }
}